package service

import (
	"delivery-server/utils/response"
	"github.com/go-xorm/xorm"
	"time"
)

// RestaurantService 餐馆服务
type RestaurantService interface {

	// UserLogin 根据用户名和密码获取用户id
	UserLogin(username, password string) (string, bool)

	// QueryRestaurantByUser 根据用户id查找其所掌管的餐馆id，返回值：餐馆id、是否存在
	QueryRestaurantByUser(userId int) (string, bool)

	// QueryStafferByUser 根据用户id查找他的员工id，返回值：员工id，餐馆id，是否存在
	QueryStafferByUser(userId int) (string, string, bool)

	// FuzzyQueryRestaurantByName 模糊查询餐馆
	FuzzyQueryRestaurantByName(query string) ([]map[string]string, bool)

	// TryToCreateRestaurant 创建餐馆事务
	TryToCreateRestaurant(name, description string, userId int) int

	// TryToJoinRestaurant 加入餐馆事务
	TryToJoinRestaurant(restaurantId, userId int) int

	// QueryApplications 查看入职申请
	QueryApplications(restaurantId int) (results []map[string]string, err error)

	// EmployStaffer 同意新员工加入
	EmployStaffer(restaurantId, userId, salary int) (err error)

	// RefuseStaffer 拒绝新员工加入
	RefuseStaffer(restaurantId, userId int) (err error)

	// QueryInformation 查询餐馆信息
	QueryInformation(restaurantId int) (results []map[string]string, err error)

	// UpdateInformation 修改餐馆信息
	UpdateInformation(restaurantId, placeId int, description string) (err error)

	// QueryStaff 查询本馆所有员工
	QueryStaff(restaurantId int) (results []map[string]string, err error)

	// DeleteStaffer 辞退员工
	DeleteStaffer(restaurantId, userId int) (err error)

	// UpdateStafferSalary 更新员工工资
	UpdateStafferSalary(restaurantId, userId, salary int) (err error)

	// InsertDish 增加菜品
	InsertDish(restaurantId, categoryId, price int, name, description string) (err error)

	// QueryDish 查看所有菜品
	QueryDish(restaurantId int) (results []map[string]string, err error)

	// DeleteDish 删除菜品
	DeleteDish(dishId int) (err error)

	// AllWaitOrder 所有的未领取订单
	AllWaitOrder(restaurantId int) (results []map[string]string, err error)

	// AllProgressOrder 所有进行中订单
	AllProgressOrder(restaurantId int) (results []map[string]string, err error)

	// StafferProgressOrder 某一员工正在进行的订单
	StafferProgressOrder(stafferId int) (results []map[string]string, err error)

	// AllFinishOrder 所有已完成订单
	AllFinishOrder(restaurantId int) (results []map[string]string, err error)

	// StafferFinishOrder 某一员工已完成订单
	StafferFinishOrder(stafferId int) (results []map[string]string, err error)

	// StartOrder 接收订单
	StartOrder(stafferId, orderId int) (code int)

	// EndOrder 完成订单
	EndOrder(stafferId, orderId int) (err error)
}

// NewRestaurantService 创建一个新的餐馆服务对象
func NewRestaurantService(engine *xorm.Engine) RestaurantService {
	return &restaurantService{
		Engine: engine,
	}
}

// 餐馆服务结构体
type restaurantService struct {
	Engine *xorm.Engine
}

// UserLogin 根据用户名和密码获取用户
func (rs restaurantService) UserLogin(username, password string) (string, bool) {

	// 根据用户名和密码来查询id
	sqlStr := "SELECT id FROM user WHERE username = ? AND password = ?"
	results, err := rs.Engine.QueryString(sqlStr, username, password)
	if err != nil {
		panic(err.Error())
	}

	// 检测是否找到匹配结果
	if len(results) > 0 {
		return results[0]["id"], true
	}
	return "", false
}

// QueryRestaurantByUser 根据用户id查找其所掌管的餐馆id，返回值：餐馆id、是否存在
func (rs restaurantService) QueryRestaurantByUser(userId int) (string, bool) {

	// 根据用户id查找其所掌管的餐馆id
	sqlStr := "SELECT id FROM restaurant WHERE master_id = ? AND invalidity = 0"
	results, err := rs.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}

	// 检测是否找到匹配结果
	if len(results) > 0 {
		return results[0]["id"], true
	}
	return "", false
}

// QueryStafferByUser 根据用户id查找他的员工id，返回值：员工id，餐馆id，是否存在
func (rs restaurantService) QueryStafferByUser(userId int) (string, string, bool) {

	// 根据用户id查找他的员工id
	sqlStr := "SELECT id, restaurant_id FROM staffer WHERE user_id = ? AND employ = 1 AND invalidity = 0"
	results, err := rs.Engine.QueryString(sqlStr, userId)
	if err != nil {
		panic(err.Error())
	}

	// 检测是否找到匹配结果
	if len(results) > 0 {
		return results[0]["id"], results[0]["restaurant_id"], true
	}
	return "", "", false

}

// 创建餐馆
func (rs restaurantService) createRestaurant(name, description string, userId int) bool {

	// 新增餐馆
	sqlStr := "INSERT INTO restaurant(name, description, master_id) VALUES (?, ?, ?)"
	_, err := rs.Engine.Exec(sqlStr, name, description, userId)
	return err == nil
}

// 加入餐馆
func (rs restaurantService) joinRestaurant(userId, restaurantId int) bool {

	// 在staffer表中添加用户与餐馆的联系
	sqlStr := "INSERT INTO staffer(user_id, restaurant_id) VALUES (?, ?)"
	_, err := rs.Engine.Exec(sqlStr, userId, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return err == nil
}

// 根据餐馆名字查询是否已被注册
func (rs restaurantService) queryRestaurantByName(name string) bool {

	// 根据餐馆名字查询餐馆id
	sqlStr := "SELECT id FROM restaurant WHERE name = ? AND invalidity = 0"
	results, err := rs.Engine.QueryString(sqlStr, name)
	if err != nil {
		panic(err.Error())
	}

	// 检测是否找到匹配结果
	return len(results) > 0
}

// 撤回申请
func (rs restaurantService) withdrawApplication(userId int) bool {

	// 将该用户的员工申请信息设置为无效
	sqlStr := "UPDATE staffer SET invalidity = 1 WHERE user_id = ?"
	_, err := rs.Engine.Exec(sqlStr, userId)
	if err != nil {
		panic(err.Error())
		return false
	}
	return true
}

// FuzzyQueryRestaurantByName 模糊查询餐馆，返回值为查询结果和是否查询到
func (rs restaurantService) FuzzyQueryRestaurantByName(query string) ([]map[string]string, bool) {

	// 根据餐馆名字称片段模糊查询餐馆id和名称
	sqlStr := "SELECT id AS idStr, name AS value FROM restaurant WHERE name like CONCAT('%', ?, '%')"
	results, err := rs.Engine.QueryString(sqlStr, query)
	if err != nil {
		panic(err.Error())
	}
	return results, len(results) > 0
}

// TryToCreateRestaurant 创建餐馆事务
func (rs restaurantService) TryToCreateRestaurant(name, description string, userId int) int {

	// 创建session对象
	session := rs.Engine.NewSession()
	defer session.Close()

	// 事务开始
	err := session.Begin()
	if err != nil {
		panic(err.Error())
		return response.ServerErrCode
	}

	// 查询餐馆名是否已被使用
	exist := rs.queryRestaurantByName(name)
	if exist {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.RestaurantExistCode
	}

	// 查询该用户是否拥有餐厅
	_, isMaster := rs.QueryRestaurantByUser(userId)
	if isMaster {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.IsMasterCode
	}

	// 查询该用户是否已加入餐厅
	_, _, isStaffer := rs.QueryStafferByUser(userId)
	if isStaffer {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.IsStafferCode
	}

	// 撤回申请数据
	withdrawSuccess := rs.withdrawApplication(userId)
	if !withdrawSuccess {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.ServerErrCode
	}

	// 插入新的餐馆数据
	createSuccess := rs.createRestaurant(name, description, userId)

	// 插入失败
	if !createSuccess {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.ServerErrCode
	}

	// 提交事务
	err = session.Commit()
	if err != nil {
		return response.ServerErrCode
	}

	return response.SuccessCode
}

// TryToJoinRestaurant 加入餐馆事务
func (rs restaurantService) TryToJoinRestaurant(userId, restaurantId int) int {
	// 创建session对象
	session := rs.Engine.NewSession()
	defer session.Close()

	// 事务开始
	err := session.Begin()
	if err != nil {
		panic(err.Error())
		return response.ServerErrCode
	}

	// 查询该用户是否拥有餐厅
	_, isMaster := rs.QueryRestaurantByUser(userId)
	if isMaster {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.IsMasterCode
	}

	// 查询该用户是否已加入餐厅
	_, _, isStaffer := rs.QueryStafferByUser(userId)
	if isStaffer {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.IsStafferCode
	}

	// 撤回申请数据
	withdrawSuccess := rs.withdrawApplication(userId)
	if !withdrawSuccess {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.ServerErrCode
	}

	// 插入新的餐馆数据
	joinSuccess := rs.joinRestaurant(userId, restaurantId)

	// 插入失败
	if !joinSuccess {
		err = session.Rollback()
		if err != nil {
			panic(err.Error())
		}
		return response.ServerErrCode
	}

	// 提交事务
	err = session.Commit()
	if err != nil {
		return response.ServerErrCode
	}

	return response.SuccessCode
}

// QueryApplications 查询入职申请
func (rs restaurantService) QueryApplications(restaurantId int) (results []map[string]string, err error) {

	// 根据申请者的id找出其部分个人信息
	sqlStr := "SELECT id, nickname, sex FROM " +
		"(SELECT user_id FROM staffer WHERE employ = 0 AND invalidity = 0 AND restaurant_id = ?) my_staffer, " +
		"user WHERE my_staffer.user_id = user.id"
	results, err = rs.Engine.QueryString(sqlStr, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// EmployStaffer 同意新员工加入
func (rs restaurantService) EmployStaffer(restaurantId, userId, salary int) (err error) {

	// 将符合条件的员工设为雇佣状态并设置初始薪资
	sqlStr := "UPDATE staffer SET employ = 1, salary = ? " +
		"WHERE employ = 0 AND invalidity = 0 AND restaurant_id = ? AND user_id = ?"
	_, err = rs.Engine.Exec(sqlStr, salary, restaurantId, userId)
	return
}

// RefuseStaffer 拒绝新员工加入
func (rs restaurantService) RefuseStaffer(restaurantId, userId int) (err error) {

	// 将有该餐馆id与该用户id的员工联系全部标记删除
	sqlStr := "UPDATE staffer SET invalidity = 1 WHERE restaurant_id = ? AND user_id = ?"
	_, err = rs.Engine.Exec(sqlStr, restaurantId, userId)
	return
}

// QueryInformation 查询餐馆信息
func (rs restaurantService) QueryInformation(restaurantId int) (results []map[string]string, err error) {
	sqlStr := "SELECT id, name, description, master_id, place_id FROM restaurant WHERE id = ?"
	results, err = rs.Engine.QueryString(sqlStr, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// UpdateInformation 修改餐馆信息
func (rs restaurantService) UpdateInformation(restaurantId, placeId int, description string) (err error) {
	sqlStr := "UPDATE restaurant SET description = ?, place_id = ? WHERE id = ?"
	_, err = rs.Engine.Exec(sqlStr, description, placeId, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// QueryStaff 查询本馆所有员工
func (rs restaurantService) QueryStaff(restaurantId int) (results []map[string]string, err error) {
	sqlStr := "SELECT id, nickname, sex, salary FROM " +
		"(SELECT user_id, salary FROM staffer WHERE employ = 1 AND invalidity = 0 AND restaurant_id = ?) my_staffer, " +
		"user WHERE my_staffer.user_id = user.id"
	results, err = rs.Engine.QueryString(sqlStr, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// DeleteStaffer 辞退员工
func (rs restaurantService) DeleteStaffer(restaurantId, userId int) (err error) {
	sqlStr := "UPDATE staffer SET invalidity = 1 WHERE restaurant_id = ? AND user_id = ?"
	_, err = rs.Engine.Exec(sqlStr, restaurantId, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// UpdateStafferSalary 更新员工工资
func (rs restaurantService) UpdateStafferSalary(restaurantId, userId, salary int) (err error) {
	sqlStr := "UPDATE staffer SET salary = ? " +
		"WHERE restaurant_id = ? AND user_id = ? AND invalidity = 0 AND employ = 1"
	_, err = rs.Engine.Exec(sqlStr, salary, restaurantId, userId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// InsertDish 增加菜品
func (rs restaurantService) InsertDish(restaurantId, categoryId, price int, name, description string) (err error) {
	sqlStr := "INSERT INTO dish(restaurant_id, category_id, name, price, description) VALUES (?, ?, ?, ?, ?)"
	_, err = rs.Engine.Exec(sqlStr, restaurantId, categoryId, name, price, description)
	if err != nil {
		panic(err.Error())
	}
	return
}

// QueryDish 查看所有菜品
func (rs restaurantService) QueryDish(restaurantId int) (results []map[string]string, err error) {
	sqlStr := "SELECT id, name, price, description, category_id FROM dish WHERE restaurant_id = ? AND invalidity = 0"
	results, err = rs.Engine.QueryString(sqlStr, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// DeleteDish 删除菜品
func (rs restaurantService) DeleteDish(dishId int) (err error) {
	sqlStr := "UPDATE dish SET invalidity = 1 WHERE id = ?"
	_, err = rs.Engine.Exec(sqlStr, dishId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// AllWaitOrder 所有的未领取订单
func (rs restaurantService) AllWaitOrder(restaurantId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity," +
		" user_id AS userId, place.name AS placeName" +
		" FROM `order`, dish, place WHERE `order`.dish_id = dish.id AND `order`.user_place = place.id" +
		" AND `order`.restaurant_id = ? AND staffer_id IS NULL"
	results, err = rs.Engine.QueryString(sqlStr, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// AllProgressOrder 所有进行中订单
func (rs restaurantService) AllProgressOrder(restaurantId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity," +
		" user_id AS userId, place.name AS placeName" +
		" FROM `order`, dish, place WHERE `order`.dish_id = dish.id AND `order`.user_place = place.id" +
		" AND staffer_id IS NOT NULL AND finished_time IS NULL AND `order`.restaurant_id = ?"
	results, err = rs.Engine.QueryString(sqlStr, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// StafferProgressOrder 某一员工正在进行的订单
func (rs restaurantService) StafferProgressOrder(stafferId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity," +
		" user_id AS userId, place.name AS placeName" +
		" FROM `order`, dish, place WHERE `order`.dish_id = dish.id AND `order`.user_place = place.id" +
		" AND staffer_id = ? AND finished_time IS NULL"
	results, err = rs.Engine.QueryString(sqlStr, stafferId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// AllFinishOrder 所有已完成订单
func (rs restaurantService) AllFinishOrder(restaurantId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity," +
		" user_id AS userId, place.name AS placeName" +
		" FROM `order`, dish, place WHERE `order`.dish_id = dish.id AND `order`.user_place = place.id" +
		" AND finished_time IS NOT NULL AND `order`.restaurant_id = ?"
	results, err = rs.Engine.QueryString(sqlStr, restaurantId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// StafferFinishOrder 某一员工已完成订单
func (rs restaurantService) StafferFinishOrder(stafferId int) (results []map[string]string, err error) {
	sqlStr := "SELECT `order`.id AS orderId, dish.name AS dishName, dish.price AS dishPrice, quantity," +
		" user_id AS userId, place.name AS placeName" +
		" FROM `order`, dish, place WHERE `order`.dish_id = dish.id AND `order`.user_place = place.id" +
		" AND finished_time IS NOT NULL AND staffer_id = ?"
	results, err = rs.Engine.QueryString(sqlStr, stafferId)
	if err != nil {
		panic(err.Error())
	}
	return
}

// StartOrder 接收订单
func (rs restaurantService) StartOrder(stafferId, orderId int) (code int) {

	session := rs.Engine.NewSession()
	defer session.Close()

	// 事务开始
	err := session.Begin()
	if err != nil {
		return response.ServerErrCode
	}

	// 查询这个订单号
	sqlStr := "SELECT * FROM `order` WHERE id = ? AND staffer_id IS NULL"
	results, err := rs.Engine.QueryString(sqlStr, orderId)
	if err != nil {
		return response.ServerErrCode
	}

	// 订单已被接取
	if len(results) == 0 {
		_ = session.Rollback()
		return response.OrderProgressCode
	}

	// 更新order
	sqlStr = "UPDATE `order` SET staffer_id = ? WHERE id = ?"
	_, err = rs.Engine.QueryString(sqlStr, stafferId, orderId)
	if err != nil {
		_ = session.Rollback()
		return response.ServerErrCode
	}

	// 结束事务
	err = session.Commit()
	if err != nil {
		return response.ServerErrCode
	}

	return response.SuccessCode
}

// EndOrder 完成订单
func (rs restaurantService) EndOrder(stafferId, orderId int) (err error) {
	sqlStr := "UPDATE `order` SET finished_time = ? WHERE id = ? AND staffer_id = ?"
	_, err = rs.Engine.QueryString(sqlStr, time.Now(), orderId, stafferId)
	if err != nil {
		panic(err.Error())
	}
	return
}
